/**
 * @file 书签管理服务
 * @description 提供书签的核心 CRUD 与云同步能力（本地明文存储）
 * 使用两表设计：BookmarkFolder（文件夹层级）和 BookmarkItem（书签项）
 */

import Realm from 'realm'
import { getDatabase } from '../index'
import { existsSync, readFileSync } from 'node:fs'
import { join } from 'node:path'
import {
  BookmarkFolderModel,
  type DatabaseResult,
  type QueryBookmarkFolderParams
} from '../models/bookmark-folder.model'
import { BookmarkItemModel, type QueryBookmarkItemParams } from '../models/bookmark-item.model'

/**
 * 书签服务（单例）
 */
export class BookmarkManagerService {
  private static instance: BookmarkManagerService

  private constructor() {}

  static getInstance(): BookmarkManagerService {
    if (!BookmarkManagerService.instance) {
      BookmarkManagerService.instance = new BookmarkManagerService()
    }
    return BookmarkManagerService.instance
  }

  /** 获取下一个可用的数值ID（兼容渲染层） - 文件夹 */
  private getNextFolderId(realm: Realm): number {
    const all = realm.objects<BookmarkFolderModel>('BookmarkFolder')
    const withId = all.filtered('id != null').sorted('id', true)
    const last = withId[0] as BookmarkFolderModel | undefined
    return (last?.id ?? 0) + 1
  }

  /** 获取下一个可用的数值ID（兼容渲染层） - 书签项 */
  private getNextItemId(realm: Realm): number {
    const all = realm.objects<BookmarkItemModel>('BookmarkItem')
    const withId = all.filtered('id != null').sorted('id', true)
    const last = withId[0] as BookmarkItemModel | undefined
    return (last?.id ?? 0) + 1
  }

  // ==================== 文件夹操作 ====================

  /** 新增文件夹 */
  async addFolder(
    input: F2.bookmark.BookmarkFolderLocal
  ): Promise<DatabaseResult<BookmarkFolderModel>> {
    try {
      const realm = getDatabase()
      const now = new Date()
      let created!: BookmarkFolderModel

      realm.write(() => {
        const nextId = this.getNextFolderId(realm)
        const parentId = input.parent_id ? new Realm.BSON.ObjectId(input.parent_id) : null

        // 计算同级顺序
        let siblings
        if (parentId) {
          siblings = realm
            .objects<BookmarkFolderModel>('BookmarkFolder')
            .filtered('parent_id == $0', parentId)
        } else {
          siblings = realm
            .objects<BookmarkFolderModel>('BookmarkFolder')
            .filtered('parent_id == null')
        }
        const nextOrder =
          siblings.length > 0 ? Math.max(...Array.from(siblings).map(f => f.sort ?? 0)) + 1 : 0

        created = realm.create('BookmarkFolder', {
          _id: new Realm.BSON.ObjectId(),
          id: nextId,
          name: input.name,
          parent_id: parentId,
          sort: input.sort ?? nextOrder,
          is_synced: false,
          server_id: null,
          created_at: now,
          updated_at: now
        }) as BookmarkFolderModel
      })

      return { success: true, data: created }
    } catch (error) {
      console.error('添加文件夹失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '添加文件夹失败' }
    }
  }

  /** 查询文件夹 */
  async queryFolders(
    params: QueryBookmarkFolderParams = {}
  ): Promise<DatabaseResult<BookmarkFolderModel[]>> {
    try {
      const realm = getDatabase()
      let q = realm.objects<BookmarkFolderModel>('BookmarkFolder')

      const { parent_id, keyword } = params
      const sortBy = params.sortBy || 'sort'
      const ascending = (params.sortOrder || 'asc') === 'asc'

      // 按父文件夹过滤
      if (parent_id !== undefined) {
        if (parent_id === null || parent_id === '') {
          q = q.filtered('parent_id == null')
        } else {
          q = q.filtered('parent_id == $0', new Realm.BSON.ObjectId(parent_id))
        }
      }

      // 关键词搜索
      if (keyword && keyword.trim()) {
        q = q.filtered('name CONTAINS[c] $0', keyword.trim())
      }

      q = q.sorted(sortBy, !ascending)

      return { success: true, data: Array.from(q) as BookmarkFolderModel[] }
    } catch (error) {
      console.error('查询文件夹失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '查询文件夹失败' }
    }
  }

  /** 更新文件夹 */
  async updateFolder(
    input: F2.bookmark.BookmarkFolderLocal
  ): Promise<DatabaseResult<BookmarkFolderModel>> {
    try {
      const realm = getDatabase()
      const folder = realm.objectForPrimaryKey(
        'BookmarkFolder',
        new Realm.BSON.ObjectId(input._id)
      ) as BookmarkFolderModel | null

      if (!folder) return { success: false, message: '文件夹不存在' }

      realm.write(() => {
        if (input.name !== undefined) folder.name = input.name
        if (input.parent_id !== undefined) {
          folder.parent_id = input.parent_id ? new Realm.BSON.ObjectId(input.parent_id) : null
        }
        if (input.sort !== undefined) folder.sort = input.sort
        folder.updated_at = new Date()
        folder.is_synced = false
      })

      return { success: true, data: folder }
    } catch (error) {
      console.error('更新文件夹失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '更新文件夹失败' }
    }
  }

  /** 删除文件夹（递归删除子文件夹和书签） */
  async deleteFolder(_id: string): Promise<DatabaseResult<boolean>> {
    try {
      const realm = getDatabase()
      const folder = realm.objectForPrimaryKey(
        'BookmarkFolder',
        new Realm.BSON.ObjectId(_id)
      ) as BookmarkFolderModel | null

      if (!folder) return { success: false, message: '文件夹不存在' }

      realm.write(() => {
        // 递归删除所有子文件夹
        const deleteRecursive = (folderId: Realm.BSON.ObjectId) => {
          const children = realm
            .objects<BookmarkFolderModel>('BookmarkFolder')
            .filtered('parent_id == $0', folderId)
          for (const child of children) {
            deleteRecursive(child._id)
          }
          // 删除该文件夹下的所有书签
          const items = realm
            .objects<BookmarkItemModel>('BookmarkItem')
            .filtered('folder_id == $0', folderId)
          realm.delete(items)
          // 删除文件夹本身
          const f = realm.objectForPrimaryKey('BookmarkFolder', folderId)
          if (f) realm.delete(f)
        }

        deleteRecursive(folder._id)
      })

      return { success: true, data: true }
    } catch (error) {
      console.error('删除文件夹失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '删除文件夹失败' }
    }
  }

  // ==================== 书签项操作 ====================

  /** 新增书签 */
  async addBookmark(input: F2.bookmark.BookmarkLocal): Promise<DatabaseResult<BookmarkItemModel>> {
    try {
      const realm = getDatabase()
      const now = new Date()
      let created!: BookmarkItemModel

      realm.write(() => {
        const nextId = this.getNextItemId(realm)
        const folderId = input.folder_id ? new Realm.BSON.ObjectId(input.folder_id) : null

        // 计算同级顺序
        let siblings
        if (folderId) {
          siblings = realm
            .objects<BookmarkItemModel>('BookmarkItem')
            .filtered('folder_id == $0', folderId)
        } else {
          siblings = realm.objects<BookmarkItemModel>('BookmarkItem').filtered('folder_id == null')
        }
        const nextOrder =
          siblings.length > 0 ? Math.max(...Array.from(siblings).map(b => b.sort ?? 0)) + 1 : 0

        created = realm.create('BookmarkItem', {
          _id: new Realm.BSON.ObjectId(),
          id: nextId,
          link: input.link,
          title: input.title,
          favicon: input.favicon || null,
          folder_id: folderId,
          sort: nextOrder,
          is_synced: false,
          server_id: null,
          created_at: now,
          updated_at: now
        }) as BookmarkItemModel
      })

      return { success: true, data: created }
    } catch (error) {
      console.error('添加书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '添加书签失败' }
    }
  }

  /** 查询书签（支持关键词、文件夹、分页与排序） */
  async queryBookmarks(
    params: QueryBookmarkItemParams = {}
  ): Promise<DatabaseResult<BookmarkItemModel[]>> {
    try {
      const realm = getDatabase()
      let q = realm.objects<BookmarkItemModel>('BookmarkItem')
      /// *, page = 1, pageSize = 50*/
      const { keyword, folder_id } = params
      const sortBy = params.sortBy || 'updated_at'
      const ascending = (params.sortOrder || 'desc') === 'asc'

      // 关键词搜索
      if (keyword && keyword.trim()) {
        q = q.filtered('(url CONTAINS[c] $0) OR (title CONTAINS[c] $0)', keyword.trim())
      }

      // 按文件夹过滤
      if (folder_id !== undefined) {
        if (folder_id === null || folder_id === '') {
          q = q.filtered('folder_id == null')
        } else {
          q = q.filtered('folder_id == $0', new Realm.BSON.ObjectId(folder_id))
        }
      }

      q = q.sorted(sortBy, !ascending)

      // 分页
      // const start = Math.max(0, (page - 1) * pageSize)
      // const end = start + pageSize
      // const list = Array.from(q).slice(start, end) as BookmarkItemModel[]

      return { success: true, data: Array.from(q) }
    } catch (error) {
      console.error('查询书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '查询书签失败' }
    }
  }

  /** 更新书签 */
  async updateBookmark(
    input: F2.bookmark.BookmarkLocal
  ): Promise<DatabaseResult<BookmarkItemModel>> {
    try {
      const realm = getDatabase()
      const item = realm.objectForPrimaryKey(
        'BookmarkItem',
        new Realm.BSON.ObjectId(input._id)
      ) as BookmarkItemModel | null

      if (!item) return { success: false, message: '书签不存在' }

      realm.write(() => {
        if (input.title !== undefined) item.title = input.title
        if (input.folder_id !== undefined) {
          item.folder_id = input.folder_id ? new Realm.BSON.ObjectId(input.folder_id) : null
        }
        if (input.sort !== undefined) item.sort = input.sort
        item.favicon = input.favicon || null
        item.updated_at = new Date()
        item.is_synced = false
      })

      return { success: true, data: item }
    } catch (error) {
      console.error('更新书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '更新书签失败' }
    }
  }

  /** 删除书签 */
  async deleteBookmark(_id: string): Promise<DatabaseResult<boolean>> {
    try {
      const realm = getDatabase()
      const item = realm.objectForPrimaryKey(
        'BookmarkItem',
        new Realm.BSON.ObjectId(_id)
      ) as BookmarkItemModel | null

      if (!item) return { success: false, message: '书签不存在' }

      realm.write(() => {
        realm.delete(item)
      })

      return { success: true, data: true }
    } catch (error) {
      console.error('删除书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '删除书签失败' }
    }
  }

  // ==================== 云同步操作 ====================

  /**
   * 将未同步的书签上传到云端
   * 注意：云端API目前不支持文件夹层级，仅同步书签项的扁平folder字段
   */
  async syncToCloud(): Promise<DatabaseResult<{ synced: number; failed: number }>> {
    try {
      const realm = getDatabase()
      const unsynced = realm
        .objects<BookmarkItemModel>('BookmarkItem')
        .filtered('is_synced == false')
      if (unsynced.length === 0) return { success: true, data: { synced: 0, failed: 0 } }

      let synced = 0
      let failed = 0
      const base = process.env.VITE_API_BASE_URL

      for (const item of unsynced) {
        try {
          // 获取文件夹路径（用于云端的folder字段）
          let folderPath = ''
          if (item.folder_id) {
            const folder = realm.objectForPrimaryKey(
              'BookmarkFolder',
              item.folder_id
            ) as BookmarkFolderModel | null
            if (folder) {
              folderPath = await this.getFolderPath(folder._id.toString())
            }
          }

          const payload = {
            id: item.server_id || 0,
            link: item.link,
            title: item.title,
            path_id: 0,
            created_at: item.created_at.getTime(),
            updated_at: item.updated_at.getTime()
          }
          const res = await fetch(`${base}/browser/saveBookmark`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ save_data: payload })
          })
          const data = (await res.json()) as {
            code: number
            message: string
            data: { save_data: F2.bookmark.Bookmark }
          }
          if (data.code !== 0) throw new Error(data.message)

          realm.write(() => {
            item.is_synced = true
            item.server_id = String(data.data.save_data.id || '')
            item.updated_at = new Date()
          })
          synced++
        } catch (error) {
          console.error('同步书签到云端失败:', error)
          failed++
        }
      }
      return { success: true, data: { synced, failed } }
    } catch (error) {
      console.error('云端同步失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '云端同步失败' }
    }
  }

  /** 获取文件夹的完整路径 */
  private async getFolderPath(folderId: string): Promise<string> {
    const realm = getDatabase()
    const folder = realm.objectForPrimaryKey(
      'BookmarkFolder',
      new Realm.BSON.ObjectId(folderId)
    ) as BookmarkFolderModel | null
    if (!folder) return ''

    const parts: string[] = [folder.name]
    let current = folder
    while (current.parent_id) {
      const parent = realm.objectForPrimaryKey(
        'BookmarkFolder',
        current.parent_id
      ) as BookmarkFolderModel | null
      if (!parent) break
      parts.unshift(parent.name)
      current = parent
    }
    return parts.join('/')
  }

  /**
   * 从云端拉取并合并书签
   * 采用 last-write-wins：比较 updated_at，较新的覆盖较旧的
   * 注意：云端folder字段会被转换为文件夹层级结构
   */
  async syncFromCloud(
    cloudBookmarks: F2.bookmark.Bookmark[]
  ): Promise<DatabaseResult<{ imported: number; updated: number }>> {
    try {
      const realm = getDatabase()
      let imported = 0
      let updated = 0

      for (const b of cloudBookmarks) {
        try {
          // 查找已存在的书签
          let existing: BookmarkItemModel | null = null
          if (b.id) {
            const list = realm
              .objects<BookmarkItemModel>('BookmarkItem')
              .filtered('server_id == $0', String(b.id))
            existing = list.length > 0 ? (list[0] as BookmarkItemModel) : null
          }
          if (!existing) {
            const list = realm
              .objects<BookmarkItemModel>('BookmarkItem')
              .filtered('url == $0 AND title == $1', b.link, b.title)
            existing = list.length > 0 ? (list[0] as BookmarkItemModel) : null
          }

          // 处理文件夹路径，创建或查找对应的文件夹
          const folderId: Realm.BSON.ObjectId | null = null

          const cloudUpdatedAt = new Date(b.update_time || Date.now())
          const cloudCreatedAt = new Date(b.create_time || b.update_time || Date.now())

          realm.write(() => {
            if (existing) {
              // last-write-wins：如果云端较新则覆盖
              if (
                !existing.updated_at ||
                cloudUpdatedAt.getTime() >= existing.updated_at.getTime()
              ) {
                existing.title = b.title
                existing.folder_id = folderId
                existing.updated_at = cloudUpdatedAt
                existing.is_synced = true
                existing.server_id = b.id ? String(b.id) : (existing.server_id ?? null)
                updated++
              }
            } else {
              const nextId = this.getNextItemId(realm)
              realm.create('BookmarkItem', {
                _id: new Realm.BSON.ObjectId(),
                id: nextId,
                link: b.link,
                title: b.title,
                folder_id: folderId,
                sort: null,
                is_synced: true,
                server_id: b.id ? String(b.id) : null,
                created_at: cloudCreatedAt,
                updated_at: cloudUpdatedAt
              })
              imported++
            }
          })
        } catch (error) {
          console.error('合并云端书签失败:', error)
        }
      }

      return { success: true, data: { imported, updated } }
    } catch (error) {
      console.error('从云端同步失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '从云端同步失败' }
    }
  }

  // ==================== 导入操作 ====================

  /**
   * 从 Chrome/Edge 的 Bookmarks JSON 导入
   * 会创建文件夹层级结构
   */
  async importFromFile(
    filePath: string,
    source: 'chrome' | 'edge' = 'chrome'
  ): Promise<DatabaseResult<{ imported: number; updated: number; foldersCreated: number }>> {
    try {
      if (!existsSync(filePath)) {
        return { success: false, message: `文件不存在: ${filePath}` }
      }
      const raw = readFileSync(filePath, 'utf8')
      const json = JSON.parse(raw)

      const realm = getDatabase()
      let imported = 0
      let updated = 0
      let foldersCreated = 0

      const toDate = (v?: string): Date | null => {
        if (!v) return null
        // Chrome/Edge: 微秒 since 1601-01-01
        const micro = Number(v)
        if (!isFinite(micro) || micro <= 0) return null
        const msSince1601 = Math.floor(micro / 1000)
        const msSince1970 = msSince1601 - 11_644_473_600_000
        return new Date(msSince1970)
      }

      // 递归解析 Chrome/Edge 书签结构，同时创建文件夹
      const visit = async (
        node: any,
        parentFolderId: Realm.BSON.ObjectId | null = null,
        siblingIndex = 0
      ): Promise<void> => {
        if (!node) return
        const type = node.type
        const name = node.name || ''

        if (type === 'folder') {
          // 创建或查找文件夹
          let folder: BookmarkFolderModel | null
          const query = parentFolderId
            ? realm
                .objects<BookmarkFolderModel>('BookmarkFolder')
                .filtered('name == $0 AND parent_id == $1', name, parentFolderId)
            : realm
                .objects<BookmarkFolderModel>('BookmarkFolder')
                .filtered('name == $0 AND parent_id == null', name)

          folder = query.length > 0 ? (query[0] as BookmarkFolderModel) : null

          if (!folder) {
            const result = await this.addFolder({
              name,
              parent_id: parentFolderId?.toString() ?? null,
              sort: siblingIndex
            })
            if (result.success && result.data) {
              folder = result.data
              foldersCreated++
            }
          }

          // 递归处理子节点
          const children: any[] = Array.isArray(node.children) ? node.children : []
          for (const [idx, child] of children.entries()) {
            await visit(child, folder?._id ?? null, idx)
          }
        } else if (type === 'url') {
          // 创建或更新书签
          const url = node.url || ''
          if (!url) return

          const guid = node.guid || node.id
          const createdAt = toDate(node.date_added) || new Date()
          const updatedAt = toDate(node.date_modified) || createdAt

          // 查找已存在的书签
          let existing: BookmarkItemModel | null = null
          if (guid) {
            const list = realm
              .objects<BookmarkItemModel>('BookmarkItem')
              .filtered('guid == $0', String(guid))
            existing = list.length > 0 ? (list[0] as BookmarkItemModel) : null
          }
          if (!existing) {
            const list = realm
              .objects<BookmarkItemModel>('BookmarkItem')
              .filtered('link == $0 AND title == $1', url, name)
            existing = list.length > 0 ? (list[0] as BookmarkItemModel) : null
          }

          realm.write(() => {
            if (existing) {
              // 简单 LWW：如果导入的更新时间更近则更新
              if (!existing.updated_at || updatedAt.getTime() >= existing.updated_at.getTime()) {
                existing.title = name
                existing.folder_id = parentFolderId
                existing.sort = siblingIndex
                existing.guid = guid || existing.guid || null
                existing.source = source
                existing.updated_at = updatedAt
                existing.is_synced = false
                updated++
              }
            } else {
              const nextId = this.getNextItemId(realm)
              realm.create('BookmarkItem', {
                _id: new Realm.BSON.ObjectId(),
                id: nextId,
                link: url,
                title: name,
                folder_id: parentFolderId,
                sort: siblingIndex,
                guid: guid || null,
                source,
                is_synced: false,
                server_id: null,
                created_at: createdAt,
                updated_at: updatedAt
              })
              imported++
            }
          })
        }
      }

      // 解析 Chrome/Edge 书签结构
      if (json && json.roots) {
        const roots = json.roots
        const rootKeys = ['bookmark_bar', 'other', 'synced']
        for (const key of rootKeys) {
          if (roots[key]?.children?.length) {
            for (const [idx, child] of roots[key].children.entries()) {
              await visit(child, null, idx)
            }
          }
        }
      } else if (Array.isArray(json)) {
        // 容错：某些导出格式可能是扁平数组
        for (const [idx, node] of json.entries()) {
          await visit(node, null, idx)
        }
      }

      return { success: true, data: { imported, updated, foldersCreated } }
    } catch (error) {
      console.error('导入书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '导入书签失败' }
    }
  }

  /**
   * 从本机浏览器默认位置导入（Windows）
   */
  async importFromBrowser(
    browser: 'chrome' | 'edge',
    profile = 'Default'
  ): Promise<DatabaseResult<{ imported: number; updated: number; foldersCreated: number }>> {
    try {
      const localAppData = process.env.LOCALAPPDATA || ''
      let filePath: string
      if (browser === 'chrome') {
        filePath = join(localAppData, 'Google/Chrome/User Data', profile, 'Bookmarks')
      } else {
        filePath = join(localAppData, 'Microsoft/Edge/User Data', profile, 'Bookmarks')
      }
      return await this.importFromFile(filePath, browser)
    } catch (error) {
      console.error('自动定位浏览器书签失败:', error)
      return { success: false, message: error instanceof Error ? error.message : '导入失败' }
    }
  }
}

export default BookmarkManagerService
